#!/usr/bin/python
# coding:utf-8

# os basic
import threading, time, os

# robot core
import jkzuc

# jaka import
import tool_function
import pylog

c = jkzuc.command()
s = jkzuc.stat()
e = jkzuc.error()
check_logger = pylog.check_logger


class MiddlewareException(Exception):

    def __init__(self, reason=""):
        super(Exception, self).__init__(reason)
        self.reason = reason


class CheckError(Exception):

    def __init__(self, errorinfo):
        Exception.__init__(self)
        self.errorinfo = errorinfo

    def __str__(self):
        return repr(self.errorinfo)


def update_jkzuc_status():
    try:
        s.poll()
    except Exception as err:
        check_logger().error("s.poll :" + repr(err))
        reason = "jkzuc.stat poll err,perhaps NML of robot dead"
        raise MiddlewareException(reason)


class robot_arm_FBT_check(threading.Thread):

    def __init__(self, threadname):
        threading.Thread.__init__(self, name=threadname)

    # input should be date str YYYYMMDD
    # output none
    def create_first_poweron_date_of_robot_serial_num(self, path, current_date):
        with open(path + "robot_serial_num.ini", "w") as time_fp:
            date_encrypted = tool_function.b32encode(current_date)
            time_fp.write(str(s.robot_serial_num))
            time_fp.write(" : ")
            time_fp.write(date_encrypted)

    def run(self):
        try:
            while True:
                update_jkzuc_status()
                if s.powered_on == 1:
                    if s.servo_version != 0:  # 刚上电可能没有伺服版本
                        path = jkzuc.jkroot_dir + "/configs/JAKA/"
                        servo = hex(s.servo_version).replace("0x", "")
                        servo_ver = int(servo[4:])
                        if servo_ver >= 2185:  # 该功能仅支持伺服2185及以上版本
                            if s.first_poweron_date == -1:
                                current_date = str(time.strftime("%Y%m%d"))  # date as int4[8](hex) then change to int32(dec)
                                servo_first_poweron_date = tool_function.hexstr2decint(current_date)
                                paramID = int(0x5A << 8) + int(0xD)  # 90 13
                                passwordID = int(0x0A << 8) + int(0x00)  # 10 00
                                c.set_servo_param(0, passwordID, 80392665)  # unlock servo param protect
                                time.sleep(1)
                                c.set_servo_param(0, paramID, servo_first_poweron_date)
                                time.sleep(1)
                                c.set_servo_param(0, passwordID, 0)  # lock servo param protect
                                check_logger().debug("[GUARANTEE DATA] first servo guarantee since {}".format(current_date))
                                self.create_first_poweron_date_of_robot_serial_num(path, current_date)
                            else:
                                servo_first_poweron_date = tool_function.decint2hexstr(s.first_poweron_date)
                                check_logger().info("[TEST] GUARANTEE DATA servo" + str(s.first_poweron_date))
                                self.create_first_poweron_date_of_robot_serial_num(path, servo_first_poweron_date)
                                check_logger().debug("[GUARANTEE DATA] servo guarantee since {}".format(servo_first_poweron_date))
                        else:
                            check_logger().debug("[GUARANTEE DATA] servo version{} too lower cannot GUARANTEE ".format(servo_ver))
                        return 0
                    else:
                        time.sleep(5)
                else:
                    time.sleep(5)
        except Exception as err:
            check_logger().error("[CHECK]" + repr(err))
            return 0


class robot_ctrlbox_FBT_check:

    def check_if_first_boost_controller(self, path):
        return os.path.isfile(path + "controller_box_FBT.b32")

    def create_first_boost_file(self, path):
        with open(path + "controller_box_FBT.b32", "w") as time_fp:
            current_date = time.strftime("%Y%m%d")
            current_date = tool_function.b32encode(current_date)
            time_fp.write(current_date)
        check_logger().debug("[GUARANTEE CHECK] create guarantee file")
        # os.chmod(path + "controller_box_FBT.b32",0444)
        if os.path.isfile(path + "controller_box_FBT.md5") == False:
            with open(path + "controller_box_FBT.md5", "w") as check_time_fp:
                with open(path + "controller_box_FBT.b32", "r") as time_fp:
                    data = time_fp.read()
                file_md5 = tool_function.getMD5(data)
                check_time_fp.write(file_md5)
            # os.chmod(path + "056677599F32E0AA",0444)
        else:
            # 增加app报错？
            raise CheckError("checkfile has existed,possible be tampered ")

    def check_first_boost_controller_file(self, path):
        if os.path.isfile(path + "controller_box_FBT.md5") == True:
            with open(path + "controller_box_FBT.md5", "r") as check_time_fp:
                check_data = check_time_fp.read()
                check_logger().info("[GUARANTEE CHECK] file value: {}".format(check_data))
            with open(path + "controller_box_FBT.b32", "r") as time_fp:
                data = time_fp.read()
                file_md5 = tool_function.getMD5(data)
                check_logger().info("[GUARANTEE CHECK] GUARANTEE file value: {}".format(file_md5))
            if check_data == file_md5:
                return True
            else:
                # 增加app报错？
                raise CheckError("MD5 not macth,possible be tampered ")
        else:
            # 增加app报错？
            raise CheckError("MD5 file missing,possible be tampered ")

    def get_first_boost_controller_time(self, path):
        with open(path + "controller_box_FBT.b32", "r") as time_fp:
            data = time_fp.read()
        try:
            guarantee = tool_function.b32decode(data)
        except Exception:
            raise CheckError("decoding err,possible be tampered ")
        year = data[0:4]
        month = data[4:6]
        day = data[6:8]
        if int(year) > 2022 and 0 <= int(month) <= 12 and 0 <= int(day) <= 31:
            check_logger().info("guarantee since : {}".format(guarantee))
            return data
        else:
            # 增加app报错？
            raise CheckError("decode data err,possible be tampered ")

    def controller_boost_check(self):
        try:
            file_path = jkzuc.jkroot_dir + "/configs/JAKA/"
            if self.check_if_first_boost_controller(file_path) == True:
                pass
            else:
                self.create_first_boost_file(file_path)
            self.check_first_boost_controller_file(file_path)
        except Exception as e:
            check_logger().error("[GUARANTEE CHECK]{}".format(repr(e)))
            check_logger().error("[GUARANTEE CHECK]{}".format(e))


# TODO:实现应用层模块监控
class CheckServer(threading.Thread):

    def __init__(self, threadname):
        threading.Thread.__init__(self, name=threadname)

    def run(self):
        pass


def check_start():
    # start controller_box First Boost Time check
    ctrlboxFBT = robot_ctrlbox_FBT_check()
    ctrlboxFBT.controller_boost_check()
    # start arm First Boost Time check
    Thread_robot_arm_FBT_check = robot_arm_FBT_check("robot_arm_FBT_check")
    Thread_robot_arm_FBT_check.setDaemon(True)
    Thread_robot_arm_FBT_check.start()

    Thread_robot_command = CheckServer("checkserver")
    Thread_robot_command.setDaemon(True)
    Thread_robot_command.start()
    while True:
        time.sleep(24 * 60 * 60)


# # for testing
# if __name__ == '__main__':

#     check_start
